/*
 * Compresor.cpp
 *
 *  Created on: 03/06/2014
 *      Author: jubuntu
 */

#include "Compresor.h"

Compresor::Compresor(char* inputFile, char* outputFile){
	this->inputFile = fopen(inputFile, "r");
	this->outputFile = fopen(outputFile, "w");
	this->miGrafo = new Grafo();
	this->miIntervalo = new Intervalo();
}

Compresor::~Compresor(){
	delete this->miGrafo;
	fclose(inputFile);
	fclose(outputFile);
	delete this->miIntervalo;
}

void Compresor::comprimirArchivo(){

	int charsProcesados = 0; //para pruebas nomás
	if (this->inputFile != NULL){ //si el archivo de entrada existe
		while(!feof(this->inputFile)&&(!ferror(this->inputFile))){ //hasta llegar al EOF
			Byte unByte = fgetc(this->inputFile); //voy leyendo los caracteres
			if (!feof(this->inputFile)){ //si no es el final de archivo
				this->comprimirChar(unByte);
				charsProcesados++; //para pruebas nomas
			}
		}
		std::cout << "Chars procesados: " << charsProcesados << std::endl; //pruebas

		//OBTENGO EL NUMERO DEL INTERVALO FINAL PARA ESCRIBIRLO EN EL ARCHIVO DE SALIDA
		std::vector<Byte>* stringFinal = this->miIntervalo->getString();

		unsigned int i = 0;

		//ESCRIBO LOS CHARS EN LA SALIDA
		for(i = 0; i < stringFinal->size(); i++){
			fputc(stringFinal->at(i), outputFile);
		}

		//COMPLETO EL ULTIMO CHAR SI HABIA QUEDADO INCOMPLETO
		if(this->miIntervalo->cantidadDeBitsEnCharIncompleto != 0){
			Byte ultimo = this->miIntervalo->charIncompleto;
			for(unsigned int j = 0; j < 8 - this->miIntervalo->cantidadDeBitsEnCharIncompleto; j++){
				ultimo = ultimo << 1;
			}
			std::cout << "					EMITO: " << (unsigned int)ultimo << std::endl;
			fputc(ultimo, outputFile);
		}

		//fputc(10,this->outputFile);
		std::cout << "Longitud string final " << stringFinal->size() << std::endl; //pruebas
	}
}

void Compresor::comprimirChar(Byte sgte){

	Byte numeros[8] = {128, 64, 32, 16, 8, 4, 2, 1};

	std::cout << "CHAR LEIDO: " << sgte << std::endl;

	//voy recorriendo los 8 bits del char
	for(int i = 0; i < 8; i++){

		//actualizo la probabilidad del cero con los datos del nodo actual
		this->miIntervalo->probabilidadDelCero = ((float)this->miGrafo->nodoActual->frecuenciaCero)/ ((float)(this->miGrafo->nodoActual->frecuenciaCero +
				(float)this->miGrafo->nodoActual->frecuenciaUno));


		if(sgte >= numeros[i]){
			std::cout << "BIT: 1" << std::endl;
			miGrafo->avanzarConUno(); //avanzo en el grafo
			miIntervalo->expandirIntervaloCon(1); //expanndo el intervalo
			std::cout << "   " <<"Frecuencia del 0: " << this->miGrafo->nodoActual->frecuenciaCero << std::endl;
			std::cout << "   " <<"Frecuencia del 1: " << this->miGrafo->nodoActual->frecuenciaUno << std::endl;
			std::cout << "   	" <<"Techo del Intervalo: " << this->miIntervalo->techo << std::endl;
			std::cout << "   	" <<"Piso del Intervalo: " << this->miIntervalo->piso << std::endl;
			miIntervalo->normalizar(); //normalizo dsp de expandir
			std::cout << "	NORMALIZO" << std::endl;
			std::cout << "   	" <<"Techo del Intervalo: " << this->miIntervalo->techo << std::endl;
			std::cout << "   	" <<"Piso del Intervalo: " << this->miIntervalo->piso << std::endl;
			std::cout << "		Bits de underflow: " << this->miIntervalo->contadorDeUnderflow << std::endl;
			sgte -= numeros[i];
		}else{
			std::cout << "BIT: 0" << std::endl;
			miGrafo->avanzarConCero();
			miIntervalo->expandirIntervaloCon(0);
			std::cout << "   " <<"Frecuencia del 0: " << this->miGrafo->nodoActual->frecuenciaCero << std::endl;
			std::cout << "   " <<"Frecuencia del 1: " << this->miGrafo->nodoActual->frecuenciaUno << std::endl;
			std::cout << "   	" <<"Techo del Intervalo: " << this->miIntervalo->techo << std::endl;
			std::cout << "   	" <<"Piso del Intervalo: " << this->miIntervalo->piso << std::endl;
			miIntervalo->normalizar();
			std::cout << "	NORMALIZO" << std::endl;
			std::cout << "   	" <<"Techo del Intervalo: " << this->miIntervalo->techo << std::endl;
			std::cout << "   	" <<"Piso del Intervalo: " << this->miIntervalo->piso << std::endl;
			std::cout << "		Bits de underflow: " << this->miIntervalo->contadorDeUnderflow << std::endl;
		}
	}
}
